package com.yxh.lib_base.ext.view

import android.content.Context
import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.text.Spannable
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
import android.text.method.LinkMovementMethod
import android.text.style.*
import android.view.View
import android.widget.TextView
import androidx.annotation.ColorInt
import com.yxh.lib_base.ext.view.textview.NoUnderlineSpan
import com.yxh.lib_base.ext.view.textview.VerticalAlignTextSpan
import com.yxh.lib_base.ext.view.textview.VerticalImageSpan


/**为 TextView 创建扩展函数，其参数为接口的扩展函数
//使用方法：
// tvTestDsl.buildSpannableString {
//    addText("我已详细阅读并同意")
//    addText("《隐私政策》"){
//        setColor("#0099FF")
//        onClick(false) {
//            //do some thing
//        }
//    }
//}*/
fun TextView.buildSpannableString(init: DslSpannableStringBuilder.() -> Unit) {
    //具体实现类
    val spanStringBuilderImpl = DslSpannableStringBuilderImpl()
    spanStringBuilderImpl.init()
    movementMethod = LinkMovementMethod.getInstance()
    //通过实现类返回SpannableStringBuilder
    text = spanStringBuilderImpl.build()
}

interface DslSpannableStringBuilder {
    //增加一段文字
    fun addText(
        text: CharSequence,
        method: (DslSpanBuilder.() -> Unit)? = null
    )
}

interface DslSpanBuilder {
    //设置文字颜色
    fun setColor(color: String)

    fun setColorInt(@ColorInt color: Int)

    //设置加粗
    fun setBold()

    fun setStyleSpan(type:()->Int)

    //字体比例
    fun setProportion(proportionb: Float)

    //删除线
    fun setStrikethrough()

    //设置Bitmap
    fun setBitmap(
        context: Context, bitmap: Bitmap, verticalAlignment: Int = DynamicDrawableSpan.ALIGN_BOTTOM
    )

    //设置Bitmap 上下居中
    fun setImageBitmapV(
        context: Context, bitmap: Bitmap, span:((VerticalImageSpan)->Unit)?=null
    )

    fun setImageDrawableV(
        drawable: Drawable?, span:((VerticalImageSpan)->Unit)?=null
    )

    fun setImageIdV(
        context: Context, drawableId: Int, span:((VerticalImageSpan)->Unit)?=null
    )

    //这个目前只支持文本对齐，如果设置了bitmap等会被去掉
    fun setVerticalAlign(fontSizeSp:Int)

    //设置点击事件
    fun onClick(useUnderLine: Boolean = true, onClick: (View) -> Unit)
}

class DslSpannableStringBuilderImpl : DslSpannableStringBuilder {
    private val builder = SpannableStringBuilder()

    //记录上次添加文字后最后的索引值
    var lastIndex: Int = 0
    var isClickable = false

    override fun addText(text: CharSequence,  method: (DslSpanBuilder.() -> Unit)?) {
        val start = lastIndex
        builder.append(text)
        lastIndex += text.length
        val spanBuilder = DslSpanBuilderImpl()
        method?.let { spanBuilder.it() }
        spanBuilder.apply {
            onClickSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
                isClickable = true
            }
            if (!useUnderLine) {
                val noUnderlineSpan = NoUnderlineSpan()
                builder.setSpan(noUnderlineSpan, start, lastIndex, Spanned.SPAN_MARK_MARK)
            }
            foregroundColorSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            styleSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            relativeSizeSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            strikethroughSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            imageSpan?.let {
                builder.setSpan(it, start, lastIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
            }
            verticalAlignTextSpan?.let {
                builder.setSpan(it, start, lastIndex, SpannableString.SPAN_INCLUSIVE_EXCLUSIVE)
            }
        }
    }

    fun build(): SpannableStringBuilder {
        return builder
    }
}

class DslSpanBuilderImpl : DslSpanBuilder {
    var foregroundColorSpan: ForegroundColorSpan? = null
    var onClickSpan: ClickableSpan? = null
    var styleSpan: StyleSpan? = null
    var relativeSizeSpan: RelativeSizeSpan? = null
    var strikethroughSpan: StrikethroughSpan? = null
    var imageSpan: ImageSpan? = null
    var useUnderLine = true
    var verticalAlignTextSpan: VerticalAlignTextSpan?=null

    override fun setColor(color: String) {
        foregroundColorSpan = ForegroundColorSpan(Color.parseColor(color))
    }

    override fun setColorInt(color: Int) {
        foregroundColorSpan = ForegroundColorSpan(color)
    }

    override fun setBold() {
        styleSpan = StyleSpan(Typeface.BOLD)
    }

    override fun setStyleSpan(type: () -> Int) {
        styleSpan = StyleSpan(type())
    }

    override fun setProportion(proportionb: Float) {
        relativeSizeSpan = RelativeSizeSpan(proportionb)
    }

    override fun setStrikethrough() {
        strikethroughSpan = StrikethroughSpan()
    }

    override fun setBitmap(context: Context, bitmap: Bitmap, verticalAlignment: Int) {
        imageSpan = ImageSpan(context, bitmap, verticalAlignment)
    }

    override fun setImageBitmapV(
        context: Context,
        bitmap: Bitmap,
        span: ((VerticalImageSpan) -> Unit)?
    ) {
        val ss = VerticalImageSpan(context, bitmap)
        span?.invoke(ss)
        imageSpan = ss
    }

    override fun setImageDrawableV(drawable: Drawable?, span: ((VerticalImageSpan) -> Unit)?) {
        val ss = VerticalImageSpan( drawable)
        span?.invoke(ss)
        imageSpan = ss
    }


    override fun setImageIdV(
        context: Context,
        drawableId: Int,
        span: ((VerticalImageSpan) -> Unit)?
    ) {
        val ss = VerticalImageSpan(context, drawableId)
        span?.invoke(ss)
        imageSpan = ss
    }

    override fun setVerticalAlign(fontSizeSp: Int) {
        verticalAlignTextSpan = VerticalAlignTextSpan(fontSizeSp)
    }

    override fun onClick(useUnderLine: Boolean, onClick: (View) -> Unit) {
        onClickSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                onClick(widget)
            }
        }
        this.useUnderLine = useUnderLine
    }
}